package com.dongzili.postgresql.common.aspect;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 本地日志缓存，当Redis不可用时临时存储日志，防止数据丢失
 */
@Component
public class LocalLogBuffer {
    // 使用阻塞队列存储日志，线程安全
    private final BlockingQueue<ApiAccessLog> logQueue = new LinkedBlockingQueue<>(10000); // 最大缓存10000条

    /**
     * 添加单条日志
     */
    public void addLog(ApiAccessLog log) {
        try {
            // 尝试添加，若队列满则等待1秒
            boolean added = logQueue.offer(log, 1, TimeUnit.SECONDS);
            if (!added) {
                // 队列满，记录错误日志（实际项目中可考虑写入文件）
                System.err.println("本地日志缓存队列已满，日志丢失: " + log.getRequestUrl());
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 批量添加日志
     */
    public void addLogs(List<ApiAccessLog> logs) {
        for (ApiAccessLog log : logs) {
            addLog(log);
        }
    }

    /**
     * 获取并清空所有日志
     */
    public List<ApiAccessLog> getAndClearLogs() {
        List<ApiAccessLog> logs = new ArrayList<>();
        logQueue.drainTo(logs);
        return logs;
    }

    /**
     * 将本地缓存的日志刷新到Redis
     */
    public void flushToRedis(RedisTemplate<String, Object> redisTemplate, String redisKey) {
        if (logQueue.isEmpty()) {
            return;
        }

        List<ApiAccessLog> logs = new ArrayList<>();
        logQueue.drainTo(logs, 100); // 每次最多刷新100条

        if (!logs.isEmpty()) {
            try {
                for (ApiAccessLog log : logs) {
                    redisTemplate.opsForList().rightPush(redisKey, log);
                }
            } catch (Exception e) {
                // 刷新失败，将日志重新放回队列
                logQueue.addAll(logs);
            }
        }
    }

    /**
     * 获取当前缓存的日志数量
     */
    public int getLogCount() {
        return logQueue.size();
    }
}
    